package cn.com.infcn.monitor.client;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ReadFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.transport.socket.SocketConnector;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.com.infcn.monitor.bean.IFCRequestBean;
import cn.com.infcn.monitor.bean.IFCResponseBean;

public class MonitorClientSync extends IoHandlerAdapter {
	
	private final Logger logger = LoggerFactory.getLogger(MonitorClientSync.class);
	private int timeout = 3000;
	
	private String host;
    private int port;
    private SocketConnector connector;
    private IoSession session;
    private ResponseListener listener;
    
    public MonitorClientSync(ResponseListener listener) {
    	this.listener = listener;

    	connector = new NioSocketConnector();
        connector.setConnectTimeoutMillis(30000L);
        connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(  
                new ObjectSerializationCodecFactory()));
        SocketSessionConfig cfg = connector.getSessionConfig();
        cfg.setUseReadOperation(true);
        
        connector.setHandler(this);
    }
    
    public boolean isConnected() {
        return (session != null && session.isConnected());
    }

    public void connect(String host, int port) {
    	connect(host, port, this.timeout);
    }
    
    public void connect(String host, int port, int timeout) {
        this.host = host;
        this.port = port;
        this.timeout = timeout;
        try {
        	session = connector.connect(new InetSocketAddress(this.host, this.port)).awaitUninterruptibly().getSession();
        }
        catch (RuntimeIoException e) {
        	logger.warn("connect gateway failed");
            listener.onExceptionCaught(e);
        }
    }
    
    public IFCResponseBean sendRequest(IFCRequestBean requestBean) {
    	if (session != null) {
    		session.write(requestBean).awaitUninterruptibly();
    		// 接收
            ReadFuture readFuture = session.read();
            if(readFuture.awaitUninterruptibly(this.timeout,TimeUnit.SECONDS)){
            	return (IFCResponseBean)readFuture.getMessage();
            }else{
            	return null;
            }
        }else {
            listener.onExceptionCaught(new Throwable("not connected"));
        }
    	return null;
    }
    
    

    public void disconnect() {
        if (session != null) {
        	session.close(true);
    		session.getService().dispose();
            session = null;
        }
    }

	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		logger.debug("messageReceived: {}", message);
		listener.messageReceived((IFCResponseBean)message);
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		logger.debug("sessionClosed");
		listener.sessionClosed();
	}

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		logger.debug("sessionOpened");
		listener.sessionOpened();
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		logger.error(cause.getMessage());
		
		listener.onExceptionCaught(cause);
	}

}
